home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / icon / packages.lha / packages / atari / ats.arc / TESTS.ARC / MINDFA.ICN < prev    next >
Text File  |  1990-03-28  |  5KB  |  215 lines

  1. ### mindfa -- minimize a DFA
  2.  
  3. record dfa(Q,S,d,q0,F)          # a DFA
  4.  
  5. procedure main()
  6.  
  7.    x := getdfa()
  8.    every 1 to 10 do
  9.       showdfa("Reduced",minimize(showdfa("Original",x)))
  10.  
  11. end
  12.  
  13. ## - getdfa() -- accept a dfa from input, return it
  14. ##
  15. procedure getdfa()
  16. local Q,S,d,q0,F
  17. local q,a
  18.  
  19.    Q := readset("Enter states (1 character names): ")
  20.    S := readset("Enter input alphabet: ")
  21.    F := readset("Enter Final states (subset of states): ")
  22.    writes("What is the start state? ")
  23.    q0 := read()
  24.    d := table()
  25.    every q := !Q & a := !S do {
  26.       writes("enter delta(",q,",",a,") = ")
  27.       d[q||":"||a] := read()
  28.       }
  29.    return dfa(Q,S,d,q0,F)
  30.  
  31. end
  32.  
  33.  
  34. ## readset(s) - get a set
  35. #
  36. procedure readset(s)
  37. local t1
  38.  
  39.    writes(s)
  40.    t1 := []
  41.    every put(t1,!cset(read()))  # the cset removes duplicates
  42.    return t1
  43.  
  44. end
  45.  
  46. ## showdfa(msg,D) -- show a dfa
  47. #
  48. procedure showdfa(msg,D)
  49. local q,a
  50.  
  51.    every 1 to 3 do write()
  52.    write(msg," Deterministic Finite Automaton is:")
  53.    write()
  54.    write("\t(Q,S,delta,q0,F)")
  55.    write()
  56.    write("where:")
  57.    write()
  58.    writeset("Q",D.Q)
  59.    writeset("S",D.S)
  60.    writeset("F",D.F)
  61.    write("\tStart state is ",D.q0)
  62.    write("\tDelta: ")
  63.    every q := !D.Q do {
  64.       every writes("\td(",q,",",a := !D.S,") = ",D.d[q||":"||a])
  65.       write()
  66.       }
  67.    return D
  68.  
  69. end
  70.  
  71. ## writeset(msg,s) -- display a set
  72. #
  73. procedure writeset(msg,s)
  74. local tmp
  75.    tmp := ""
  76.    every tmp ||:= !s || ","
  77.    write("\t",msg," = {",tmp[1:-1],"}")
  78.    return
  79. end
  80.  
  81. ## minimize(D) -- minimize a dfa
  82. #
  83. global distab, dlists
  84.  
  85. procedure minimize(D)
  86. local F,QF
  87. local p,q,a,cs
  88.  
  89.    distab := table()
  90.    dlists := table()
  91.    F := D.F
  92.    QF := diff(D.Q,D.F)
  93.    every p := !F & q := !QF do
  94.       distab[cset(p||q)] := "X"
  95.    every ((p := !F & q := !F) |
  96.           (p := !QF & q := !QF)) & p ~== q do
  97.       if \distab[cset(D.d[p||":"||(a:=!D.S)]||D.d[q||":"||a])] then {
  98.          distab[cset(p||q)] := "X"
  99.          marklists(dlists[cset(p||q)])
  100.          }
  101.       else
  102.          every a := !D.S do
  103.             if D.d[p||":"||a] ~== D.d[q||":"||a] then {
  104.                cs := cset(D.d[p||":"||a]||D.d[q||":"||a])
  105.                if cs == cset(p||q) then next
  106.                /dlists[cs] := []
  107.                put(dlists[cs],cset(p||q))
  108.                }
  109.  
  110.    return makemdfa(D,distab)
  111.  
  112. end
  113.  
  114. ## marklists(l) -- recursively mark the pair of nodes
  115. #                  on list l.
  116. procedure marklists(l)
  117. local e
  118.  
  119.    if /l then return
  120.    every e := !l do {
  121.       distab[e] := "X"
  122.       marklists(dlists[e])
  123.       }
  124.    return
  125.  
  126. end
  127.  
  128. ## makemdfa(D,DT) -- Use the table from the minimization
  129. #                    to construct the minimal dfa
  130. procedure makemdfa(D,DT)
  131. local elist, etab, qset, tlist, echeck
  132. local p, q, Delta, q0
  133.  
  134.    etab := table()              # table of new states
  135.    qset := ''
  136.    every p := !D.Q do {
  137.       qset ++:= p
  138.       plike := equiv(p,etab) | cset(p)
  139.       every q := !diff(D.Q,qset) & p ~== q do
  140.          if /distab[cset(p||q)] then {
  141.             plike ++:= equiv(q,etab) | q
  142.             }
  143.       etab[plike] := plike
  144.       }
  145.    tlist := []
  146.    elist := []
  147.    Delta := table()
  148.    q0 := equiv(D.q0,etab)       # start state of reduced machine
  149.    put(tlist,q0)
  150.    put(elist,q0)                # only worry about states reachable
  151.                                 #   from [q0]
  152.    echeck := table()            #   keep track of states
  153.    echeck[q0] := q0
  154.    while q := get(tlist) do
  155.       every a := !D.S do {
  156.          Delta[q||":"||a] := equivdelta(q,a,D,etab)
  157.          if /echeck[Delta[q||":"||a]] then {
  158.             echeck[Delta[q||":"||a]] := Delta[q||":"||a]
  159.             put(tlist,Delta[q||":"||a])
  160.             put(elist,Delta[q||":"||a])
  161.             }
  162.          }
  163.  
  164.    return dfa(elist,D.S,Delta,q0,finalstates(D,elist))
  165. end
  166.  
  167. ## equiv(q,el) -- return the equivalence class in el containing q
  168. #
  169. procedure equiv(q,el)
  170.    every p := !el do
  171.       if p++q == p then return p
  172. end
  173.  
  174. ## equivdelta(p,a,D,el) -- apply delta to equiv. classes
  175. #
  176. procedure equivdelta(p,a,D,el)
  177. local q, r
  178.    q := !p               # any state in equiv. class p
  179.    r := D.d[q||":"||a]   # find state in original dfa
  180.  
  181.    return equiv(r,el)    # return its equivalence class
  182. end
  183.  
  184.  
  185. ## finalstates(D,el) -- build the set of final states
  186. #
  187. procedure finalstates(D,el)
  188. local flist, p, q
  189.  
  190.    ftab := table()
  191.    every p := !D.F do
  192.       ftab[q := equiv(p,el)] := q
  193.    flist := []
  194.    every put(flist,(!sort(ftab))[1])
  195.    return flist
  196. end
  197.  
  198.  
  199. ## diff(l1,l2) -- return the difference of two sets
  200. #
  201. procedure diff(l1,l2)
  202. local l,t1,t2
  203.  
  204.    t1 := ''
  205.    every t1 ++:= !l1
  206.  
  207.    t2 := ''
  208.    every t2 ++:= !l2
  209.  
  210.    l := []
  211.    every put(l,!(t1--t2))
  212.    if *l = 0 then fail
  213.    return l
  214. end
  215.